package com.javablog.elasticsearch.query;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.javablog.elasticsearch.es.entity.EsProduct;
import com.javablog.elasticsearch.es.entity.PageInfo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.elasticsearch.action.search.*;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.Scroll;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext;
import org.elasticsearch.search.suggest.phrase.PhraseSuggestionBuilder;
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.*;

import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;

@Service("baseQuery1111")
public class BaseQueryService<T> {
    private final static Logger log = LoggerFactory.getLogger(BaseQueryService.class);

    @Autowired
    private RestHighLevelClient restHighLevelClient;


    /**
     * comprehensiveQueryEventVO是我封装的一个查询条件实体对象，这里是封装查询条件
     *
     * @param comprehensiveQueryEventVO
     * @return
     */
    public SearchSourceBuilder getSearchSourceBuilder(ComprehensiveQueryEventVO comprehensiveQueryEventVO) {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.from((comprehensiveQueryEventVO.getPageNum() - 1) * comprehensiveQueryEventVO.getPageSize());
        sourceBuilder.size(comprehensiveQueryEventVO.getPageSize());
        return sourceBuilder;
    }

    /**
     * 分页查询某个字段里含有某个关键词的文档
     *
     * @param indexName 索引名
     * @return 返回结果列表
     * @throws IOException
     */
    public <T> PageInfo<T> termQuery(SearchSourceBuilder searchSourceBuilder, String indexName, Class<T> s) throws IOException {
        List<Map<String, Object>> response = new ArrayList<>();
        SearchRequest searchRequest = new SearchRequest(indexName);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        log.info("命中的数量为:{}", hits.getTotalHits());
        SearchHit[] h = hits.getHits();
        JSONArray jsonArray = new JSONArray();
        for (SearchHit hit : h) {
            JSONObject jsonObject = JSON.parseObject(hit.getSourceAsString());
            jsonArray.add(jsonObject);
            response.add(hit.getSourceAsMap());
        }
        // 封装分页
        List<T> list = jsonArray.toJavaList(s);
        PageInfo<T> page = new PageInfo<>();
        page.setList(list);
        page.setPageNum(searchSourceBuilder.from());
        page.setPageSize(searchSourceBuilder.size());
        page.setTotal((int) hits.getTotalHits().value);
        page.setPages(page.getTotal() == 0 ? 0 : (page.getTotal() % page.getPageSize() == 0 ? page.getTotal() / page.getPageSize() : (page.getTotal() / page.getPageSize()) + 1));
        page.setHasNextPage(page.getPageNum() < page.getPages());
        return page;
    }


    /**
     * 自动补全
     *
     * @param suggestField       指定哪个字段(搜索)补全
     * @param condition          查询条件
     * @param SUGGESTION_CONTEXT 补全加额外查询条件 比如热度靠前的
     */
    public List<String> getSuggestKeyword(String suggestField, String condition, Map<String, List<? extends ToXContent>> SUGGESTION_CONTEXT, String indexName) {
        CategoryQueryContext enableCat = CategoryQueryContext.builder().setCategory("1").build();
        CategoryQueryContext deleteStatusCat = CategoryQueryContext.builder().setCategory("0").build();
//        CategoryQueryContext deleteStatusCat1 = CategoryQueryContext.builder().setCategory(condition).build();
        Map<String, List<? extends ToXContent>> contexts = new HashMap<>();
        List<CategoryQueryContext> list = new ArrayList<>(1);
        list.add(enableCat);
        contexts.put("enable_cat", list);
        List<CategoryQueryContext> list2 = new ArrayList<>(1);
        list2.add(deleteStatusCat);
        contexts.put("delete_status_cat", list2);
        List<CategoryQueryContext> list3 = new ArrayList<>(1);
//        list3.add(deleteStatusCat1);
//        contexts.put("goods_name_cat",list3);
        SUGGESTION_CONTEXT = contexts;
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //suggestField为指定在哪个字段搜索，suggestValue为输入内容，TEN为10，代表输出显示最大条数
        CompletionSuggestionBuilder suggestionBuilderDistrict =
                new CompletionSuggestionBuilder(suggestField).text(condition).size(2).skipDuplicates(true).contexts(SUGGESTION_CONTEXT);
        SuggestBuilder suggestBuilder = new SuggestBuilder();
        suggestBuilder.addSuggestion(indexName + suggestField, suggestionBuilderDistrict);
//        List<String> keywords=new ArrayList<>();
        List<String> keywords = getStrings(suggestField, indexName, searchSourceBuilder, suggestBuilder);
//        if (CollectionUtils.isEmpty(keywords)){
//            PhraseSuggestionBuilder termSuggestionBuilder =
//                    new PhraseSuggestionBuilder(suggestField).text(condition).size(2);
//            SuggestBuilder suggestBuilder1 = new SuggestBuilder();
//            suggestBuilder1.addSuggestion(indexName+suggestField, termSuggestionBuilder);
//            List<String> strings = getStrings(suggestField, indexName, searchSourceBuilder, suggestBuilder1);
//            log.info("--------{}",JSON.toJSONString(strings));
//        }
        return keywords;
    }

    private List<String> getStrings(String suggestField, String indexName, SearchSourceBuilder searchSourceBuilder, SuggestBuilder suggestBuilder) {
        searchSourceBuilder.suggest(suggestBuilder);
        SearchRequest searchRequest = new SearchRequest(indexName);
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = null;
        try {
            response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("IOException:{}", e);
        }
        Suggest suggest = response.getSuggest();
        List<String> keywords = null;
        if (suggest != null) {
            keywords = new ArrayList<>();
            List<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> entries =
                    suggest.getSuggestion(indexName + suggestField).getEntries();
            for (Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> entry : entries) {
                for (Suggest.Suggestion.Entry.Option option : entry.getOptions()) {
                    String keyword = option.getText().string();
                    if (!StringUtils.isEmpty(keyword)) {
                        if (keywords.contains(keyword)) {
                            continue;
                        }
                        keywords.add(keyword);
                        if (keywords.size() >= 10) {
                            break;
                        }
                    }
                }
            }
        }
        return keywords;
    }


    /**
     * 拼音Fuzzy查询
     *
     * @param field
     * @param value
     * @param highlightField
     * @param preTag
     * @param postTag
     * @param index
     * @return
     */
    public List<String> listSearchByPinyin(String field, String value, String highlightField, String preTag, String postTag, String index) {
        List<String> result = new LinkedList<>();
        SearchRequest request = new SearchRequest(index);
        FuzzyQueryBuilder queryBuilder = QueryBuilders.fuzzyQuery(field, value)
                .fuzziness(Fuzziness.TWO)
                .prefixLength(0)
                .maxExpansions(10);
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //高亮字段
        highlightBuilder.field(highlightField);
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");

        SearchSourceBuilder requestBuilder = new SearchSourceBuilder();
        requestBuilder
                .query(queryBuilder)
        ;
        requestBuilder.highlighter(highlightBuilder);
        request.source(requestBuilder);

        SearchResponse response = null;
        try {
            response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("IOException:{}", e);
        }

        System.out.println(response.getClusters().toString());

        System.out.println(requestBuilder.toString());

        SearchHits searchHits = response.getHits();
        List<Map<String, Object>> list = setSearchResponse(response);
//        searchHits.forEach(i->{
//            System.out.println(i.getIndex());
//            System.out.println(i.getId());
//            System.out.println(i.getSourceAsString());
//
//            Text highlightFragment = i.getHighlightFields().get(highlightField).getFragments()[0];
//
//            result.add(highlightFragment.toString());
//
//            System.out.println();
//
//        });


        return result;
    }


    public List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse) {
        //解析结果
        ArrayList<Map<String, Object>> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            Map<String, HighlightField> high = hit.getHighlightFields();
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            high.forEach((key, value) -> {
                if (value != null) {
                    Text[] texts = value.fragments();
                    String nTitle = "";
                    for (Text text : texts) {
                        nTitle += text;
                    }
                    //替换
                    sourceAsMap.put(key, nTitle);
                }
            });
            list.add(sourceAsMap);
        }
        list.forEach(System.out::println);
        return list;
    }




    public void search(String keyword, Long brandId, Long productCategoryId, Integer pageNum, Integer pageSize, Integer sort,Class<T> s) {
//        Pageable pageable = PageRequest.of(pageNum, pageSize);
        SearchRequest request=new SearchRequest("pms");
        SearchSourceBuilder nativeSearchQueryBuilder = new SearchSourceBuilder();
        //分页
        nativeSearchQueryBuilder.from(pageNum);
        nativeSearchQueryBuilder.size(pageSize);
        //过滤
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (brandId != null || productCategoryId != null) {

            if (brandId != null) {
                boolQueryBuilder.must(QueryBuilders.termQuery("brandId", brandId));
            }
            if (productCategoryId != null) {
                boolQueryBuilder.must(QueryBuilders.termQuery("productCategoryId", productCategoryId));
            }
            nativeSearchQueryBuilder.query(boolQueryBuilder);
        }
        //搜索
        if (StringUtils.isEmpty(keyword)) {
            nativeSearchQueryBuilder.query(QueryBuilders.matchAllQuery());
        } else {
            List<FunctionScoreQueryBuilder.FilterFunctionBuilder> filterFunctionBuilders = new ArrayList<>();
            filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("name", keyword),
                    ScoreFunctionBuilders.weightFactorFunction(10)));
            filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("subTitle", keyword),
                    ScoreFunctionBuilders.weightFactorFunction(5)));
            filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("keywords", keyword),
                    ScoreFunctionBuilders.weightFactorFunction(2)));
            FunctionScoreQueryBuilder.FilterFunctionBuilder[] builders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[filterFunctionBuilders.size()];
            filterFunctionBuilders.toArray(builders);
            FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(builders)
                    .scoreMode(FunctionScoreQuery.ScoreMode.SUM)
                    .setMinScore(2);
//            FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(builders).scoreMode(FunctionScoreQuery.ScoreMode.SUM).boostMode(CombineFunction.SUM);
            nativeSearchQueryBuilder.query(functionScoreQueryBuilder);
        }
        //排序
        if(sort==1){
            //按新品从新到旧
            nativeSearchQueryBuilder.sort(SortBuilders.fieldSort("id").order(SortOrder.DESC));
        }else if(sort==2){
            //按销量从高到低
            nativeSearchQueryBuilder.sort(SortBuilders.fieldSort("sale").order(SortOrder.DESC));
        }else if(sort==3){
            //按价格从低到高
            nativeSearchQueryBuilder.sort(SortBuilders.fieldSort("price").order(SortOrder.ASC));
        }else if(sort==4){
            //按价格从高到低
            nativeSearchQueryBuilder.sort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
        }else{
            //按相关度
            nativeSearchQueryBuilder.sort(SortBuilders.scoreSort().order(SortOrder.DESC));
        }
//        nativeSearchQueryBuilder.sort(SortBuilders.scoreSort().order(SortOrder.DESC));
        request.source(nativeSearchQueryBuilder);
        SearchResponse response = null;
        try {
            response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("IOException:{}", ExceptionUtils.getStackTrace(e));
        }
        SearchHits hits = response.getHits();
        log.info("命中的数量为:{}", hits.getTotalHits());
        SearchHit[] h = hits.getHits();
        JSONArray jsonArray = new JSONArray();
        for (SearchHit hit : h) {
            JSONObject jsonObject = JSON.parseObject(hit.getSourceAsString());
            jsonArray.add(jsonObject);
        }
        // 封装分页
        List<T> list = jsonArray.toJavaList(s);
        System.out.println(JSON.toJSONString(list));
        PageInfo<T> page = new PageInfo<>();
        page.setList(list);
        page.setPageNum(pageNum);
        page.setPageSize(pageSize);
        page.setTotal((int) hits.getTotalHits().value);
        page.setPages(page.getTotal() == 0L ? 0 : (page.getTotal() % page.getPageSize() == 0 ? page.getTotal() / page.getPageSize() : (page.getTotal() / page.getPageSize()) + 1));
        page.setHasNextPage(page.getPageNum() < page.getPages());

    }






























//    /**
//     * 查询某个字段里含有多个关键词的文档
//     * @param indexName   索引名
//     * @param typeName    TYPE
//     * @param fieldName   字段名称
//     * @param fieldValues  字段值
//     * @return 返回结果列表
//     * @throws IOException
//     */
//    public List<Map<String,Object>> termsQuery(String indexName, String typeName, String fieldName, String... fieldValues) throws IOException {
//        List<Map<String,Object>> response =new ArrayList<>();
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        sourceBuilder.query(QueryBuilders.termsQuery(fieldName,fieldValues));
//        sourceBuilder.from(0);
//        sourceBuilder.size(10);
//        searchRequest.source(sourceBuilder);
//        log.info("source:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//            response.add(hit.getSourceAsMap());
//        }
//        return response;
//    }
//
//    /**
//     * 查询所有文档
//     * @param indexName   索引名称
//     * @param typeName    TYPE
//     * @throws IOException
//     */
//    @Override
//    public T queryAll(String indexName, String typeName) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(matchAllQuery());
//        searchSourceBuilder.from(0);
//        searchSourceBuilder.size(20);
//        searchRequest.source(searchSourceBuilder);
//        log.info("source:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println(hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        List<Map<String,Object>> list=new ArrayList<>();
//        for (SearchHit hit : h) {
//            list.add(hit.getSourceAsMap());
//        }
//        return (T) list;
//    }
//
//    /**
//     * match 搜索
//     * @param indexName 索引名称
//     * @param typeName  TYPE名称
//     * @param field     字段
//     * @param keyWord   搜索关键词
//     * @throws IOException
//     */
//    @Override
//    public void queryMatch(String indexName, String typeName, String field,String keyWord) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
////        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.matchQuery(field,keyWord));
//        searchRequest.source(searchSourceBuilder);
//        log.info("source:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    /**
//     * 布尔match查询
//     * @param indexName    索引名称
//     * @param typeName     TYPE名称
//     * @param field        字段名称
//     * @param keyWord      关键词
//     * @param op           该参数取值为or 或 and
//     * @throws IOException
//     */
//    @Override
//    public void queryMatchWithOperate(String indexName, String typeName, String field,String keyWord,Operator op) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.matchQuery(field,keyWord).operator(op));
//        searchRequest.source(searchSourceBuilder);
//        log.info("source:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    /**
//     *该查询通过字段fields参数作用在多个字段上。
//     * @param indexName  索引名称
//     * @param typeName   TYPE名称
//     * @param keyWord    关键字
//     * @param fieldNames  字段
//     * @throws IOException
//     */
//    @Override
//    public void queryMulitMatch(String indexName, String typeName,String keyWord,String ...fieldNames) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.multiMatchQuery(keyWord,fieldNames));
//        searchRequest.source(searchSourceBuilder);
//        log.info("source:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    /**
//     * 对查询词语分析后构建一个短语查询
//     * @param indexName    索引名称
//     * @param typeName     TYPE名称
//     * @param fieldName    字段名称
//     * @param keyWord      关键字
//     * @throws IOException
//     */
//    @Override
//    public void queryMatchPhrase(String indexName, String typeName,String fieldName,String keyWord) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.matchPhraseQuery(fieldName,keyWord));
//        searchRequest.source(searchSourceBuilder);
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    @Override
//    public void queryMatchPrefixQuery(String indexName, String typeName,String fieldName,String keyWord) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.matchPhrasePrefixQuery(fieldName,keyWord).maxExpansions(1));
//        searchRequest.source(searchSourceBuilder);
//        log.info("source:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    /**
//     * 查出指定_id的文档
//     * @param indexName   索引名称
//     * @param typeName    TYPE名称
//     * @param ids         _id值
//     * @throws IOException
//     */
//    @Override
//    public void idsQuery(String indexName, String typeName,String ... ids) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.idsQuery().addIds(ids));
//        searchRequest.source(searchSourceBuilder);
//        log.info("string:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    /**
//     * 查找某字段以某个前缀开头的文档
//     * @param indexName 索引名称
//     * @param typeName  TYPE名称
//     * @param field     字段
//     * @param prefix    前缀
//     * @throws IOException
//     */
//    @Override
//    public void prefixQuery(String indexName, String typeName, String field, String prefix) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.prefixQuery(field,prefix));
//        searchRequest.source(searchSourceBuilder);
//        log.info("string:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    /**
//     * 查找某字段以某个前缀开头的文档
//     * @param indexName 索引名称
//     * @param typeName  TYPE名称
//     * @param field     字段
//     * @param value     查询关键字
//     * @throws IOException
//     */
//    @Override
//    public void fuzzyQuery(String indexName, String typeName,String field,String value) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.fuzzyQuery(field,value).prefixLength(2));
//        searchRequest.source(searchSourceBuilder);
//        log.info("string:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    /**
//     * 以通配符来查询
//     * @param indexName     索引名称
//     * @param typeName      TYPE名称
//     * @param fieldName     字段名称
//     * @param wildcard      通配符
//     * @throws IOException
//     */
//    @Override
//    public void wildCardQuery(String indexName, String typeName, String fieldName, String wildcard) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.wildcardQuery(fieldName, wildcard));
//        searchRequest.source(searchSourceBuilder);
//        log.info("string:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    /**
//     * 范围查询
//     * @param indexName     索引名称
//     * @param typeName      TYPE名称
//     * @param fieldName     字段名称
//     * @param from
//     * @param to
//     * @throws IOException
//     */
//    @Override
//    public void rangeQuery(String indexName, String typeName, String fieldName, int from,int to) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
////        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.rangeQuery(fieldName).from(from).to(to));
//        searchRequest.source(searchSourceBuilder);
//        log.info("string:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    /**
//     *正则表达示查询
//     * @param indexName     索引名称
//     * @param typeName      TYPE名称
//     * @param fieldName     字段名称
//     * @param regexp        正则表达示
//     * @throws IOException
//     */
//    @Override
//    public void regexpQuery(String indexName, String typeName, String fieldName, String regexp) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.regexpQuery(fieldName,regexp));
//        searchRequest.source(searchSourceBuilder);
//        log.info("string:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//    @Override
//    public void moreLikeThisQuery(String indexName, String typeName, String[] fieldNames, String[] likeTexts) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        searchRequest.types(typeName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.moreLikeThisQuery(likeTexts).minTermFreq(1));
//        searchRequest.source(searchSourceBuilder);
//        log.info("string:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
////    @Override
//    public void scrollQuery(String indexName, String typeName) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        //初始化scroll
//        //值不需要足够长来处理所有数据—它只需要足够长来处理前一批结果。每个滚动请求(带有滚动参数)设置一个新的过期时间。
//        final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L)); //设定滚动时间间隔
//        searchRequest.scroll(scroll);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(matchAllQuery());
//        searchSourceBuilder.size(5); //设定每次返回多少条数据
//        searchRequest.source(searchSourceBuilder);
//        log.info("string:" + searchRequest.source());
//        SearchResponse searchResponse = null;
//        try {
//            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        String scrollId = searchResponse.getScrollId();
//        SearchHit[] searchHits = searchResponse.getHits().getHits();
//        System.out.println("-----首页-----");
//        for (SearchHit searchHit : searchHits) {
//            log.info(searchHit.getSourceAsString());
//        }
//        //遍历搜索命中的数据，直到没有数据
//        while (searchHits != null && searchHits.length > 0) {
//            SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
//            scrollRequest.scroll(scroll);
//            log.info("string:" + scrollRequest.toString());
//            try {
//                searchResponse = restHighLevelClient.scroll(scrollRequest, RequestOptions.DEFAULT);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            scrollId = searchResponse.getScrollId();
//            searchHits = searchResponse.getHits().getHits();
//            if (searchHits != null && searchHits.length > 0) {
//                System.out.println("-----下一页-----");
//                for (SearchHit searchHit : searchHits) {
//                    log.info(searchHit.getSourceAsString());
//                }
//            }
//
//        }
//        //清除滚屏
//        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
//        clearScrollRequest.addScrollId(scrollId);//也可以选择setScrollIds()将多个scrollId一起使用
//        ClearScrollResponse clearScrollResponse = null;
//        try {
//            clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest,RequestOptions.DEFAULT);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        boolean succeeded = clearScrollResponse.isSucceeded();
//        System.out.println("succeeded:" + succeeded);
//    }
//
//
//
//
//    @Override
//    public Map<String,Object> scrollQuery1(String indexName, String scrollId) throws IOException {
//        Map<String,Object> map=new HashMap<>();
//        List<String> list=new ArrayList<>();
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        //初始化scroll
//        //值不需要足够长来处理所有数据—它只需要足够长来处理前一批结果。每个滚动请求(带有滚动参数)设置一个新的过期时间。
//        final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L)); //设定滚动时间间隔
//
//        searchRequest.scroll(scroll);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(matchAllQuery());
//        searchSourceBuilder.size(1000); //设定每次返回多少条数据
//        searchRequest.source(searchSourceBuilder);
////        log.info("string:" + searchRequest.source());
//        SearchResponse searchResponse = null;
//        if (StringUtils.isNotEmpty(scrollId)){
//            SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
//            scrollRequest.scroll(scroll);
////            log.info("string:" + scrollRequest.toString());
//            try {
//                searchResponse = restHighLevelClient.scroll(scrollRequest, RequestOptions.DEFAULT);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            scrollId = searchResponse.getScrollId();
//            SearchHit[] searchHits = searchResponse.getHits().getHits();
//            if (searchHits != null && searchHits.length > 0) {
//                System.out.println("-----下一页-----");
//                for (SearchHit searchHit : searchHits) {
//                    list.add(searchHit.getSourceAsString());
//                    log.info(searchHit.getSourceAsString());
//                }
//            }
//        }else {
//            try {
//                searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            scrollId = searchResponse.getScrollId();
//            SearchHit[] searchHits = searchResponse.getHits().getHits();
//            System.out.println("-----首页-----");
//            for (SearchHit searchHit : searchHits) {
//                list.add(searchHit.getSourceAsString());
//                log.info(searchHit.getSourceAsString());
//            }
//        }
//
//        //清除滚屏
////        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
////        clearScrollRequest.addScrollId(scrollId);//也可以选择setScrollIds()将多个scrollId一起使用
////        ClearScrollResponse clearScrollResponse = null;
////        try {
////            clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest,RequestOptions.DEFAULT);
////        } catch (IOException e) {
////            e.printStackTrace();
////        }
////        boolean succeeded = clearScrollResponse.isSucceeded();
////        System.out.println("succeeded:" + succeeded);
//        map.put("scrollId",scrollId);
//        map.put("result", JSON.toJSONString(list));
//
//        return map;
//    }
//
//    public void cc(String indexName, String typeName, String field,String keyWord,Operator op,Class<?> t) throws IOException {
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.matchQuery(field,keyWord).operator(op));
//        searchRequest.source(searchSourceBuilder);
//        log.info("source:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        for (SearchHit hit : h) {
//            System.out.println("结果"+hit.getSourceAsMap());
//        }
//    }
//
//
//
//
//
//    private static ObjectMapper objectMapper=new ObjectMapper();
//    /**
//     *
//     * @Title: jsonToObject
//     * @author kaka
//     * @Description: 一个jsonStr包含多个java对象，取其中一个转化为java对象的方法
//     * @param @param <T>
//     * @param @param content json格式的字符串
//     * @param @param key 要转换的子json串的key
//     * @param @param clazz 目标类型
//     * @param @return 返回类型为T的对象
//     * @param @throws Exception
//     * @return T
//     * @throws
//     */
//    public static <T> T jsonToObject(List<Map<String,Object>> content, String key,Class clazz) throws Exception {
//        JSONArray jsonArray = new JSONArray();
//        jsonArray.addAll(content);
//        List list = jsonArray.toJavaList(clazz);
//        return (T) list;
//    }
//
//
//    public  <E> List<E> toList(Class<E> clazz,String indexName,String field,String keyWord,Operator op)throws Exception {
//        List<Map<String,Object>> mapList=new ArrayList<>();
//        SearchRequest searchRequest = new SearchRequest(indexName);
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.matchQuery(field,keyWord).operator(op));
////        searchSourceBuilder.
//        searchRequest.source(searchSourceBuilder);
//        log.info("source:" + searchRequest.source());
//        SearchResponse searchResponse =  restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
//        SearchHits hits = searchResponse.getHits();
//        System.out.println("count:"+hits.getTotalHits());
//        SearchHit[] h =  hits.getHits();
//        List<E> list=new ArrayList<>();
//        long start1=System.currentTimeMillis();
//        List<String> valueList=new ArrayList<>();
//        for (SearchHit hit : h) {
//            E e = JSON.parseObject(hit.getSourceAsString(), clazz);
////            valueList.add(hit.getSourceAsString());
//            list.add(e);
////            mapList.add(hit.getSourceAsMap());
//        }
////        long start1=System.currentTimeMillis();
////        List<E> accOutCaseHelpExamList= JSON.parseObject(JSON.toJSONString(mapList), new TypeReference<List<E>>() {});
//        long end1=System.currentTimeMillis();
//        System.out.println(end1-start1);
//        return list;
//    }
//
//    public static <T> T map2bean(Map<String, Object> map, Class<T> clz) throws Exception {
//        //创建一个需要转换为的类型的对象
//        T obj = clz.newInstance();
//        //从Map中获取和属性名称一样的值，把值设置给对象(setter方法)
//
//        //得到属性的描述器
//        BeanInfo b = Introspector.getBeanInfo(clz, Object.class);
//        PropertyDescriptor[] pds = b.getPropertyDescriptors();
//        for (PropertyDescriptor pd : pds) {
//            //得到属性的setter方法
//            Method setter = pd.getWriteMethod();
//            //得到key名字和属性名字相同的value设置给属性
//            setter.invoke(obj, map.get(pd.getName()));
//        }
//        return obj;
//    }
//
//    public static <T> T map2Object(Map<String, Object> map, Class<T> clazz) {
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//
//        if (map == null) {
//            return null;
//        }
//        T obj = null;
//        try {
//            // 使用newInstance来创建对象
//            obj = clazz.newInstance();
//            // 获取类中的所有字段
//            Field[] fields = obj.getClass().getDeclaredFields();
//            for (Field field : fields) {
//                int mod = field.getModifiers();
//                // 判断是拥有某个修饰符
//                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
//                    continue;
//                }
//                // 当字段使用private修饰时，需要加上
//                field.setAccessible(true);
//                // 获取参数类型名字
//                String filedTypeName = field.getType().getName();
//                // 判断是否为时间类型，使用equalsIgnoreCase比较字符串，不区分大小写
//                // 给obj的属性赋值
//                if (filedTypeName.equalsIgnoreCase("java.util.date")) {
//                    String datetimestamp = (String) map.get(field.getName());
//                    if (datetimestamp.equalsIgnoreCase("null")) {
//                        field.set(obj, null);
//                    } else {
//                        field.set(obj, sdf.parse(datetimestamp));
//                    }
//                } else {
//                    field.set(obj, map.get(field.getName()));
//                }
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return obj;
//    }

}
